<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
</html>

<script>
    "use strict";
    /**
     * var是全局作用域, let只在当前代码块有效
     */
    {
        // let a = 8;   // a变量只在花括号内有效
        var a = 8
        var b = 9;
    }
    console.log(a); //ReferenceError: a is not defined
    console.log(b);  //9

    console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>')

    /**
     * let变量不能重复声明 var可以被重复声明变量
     */
    for (var i = 0; i <10; i++) {
        setTimeout(function() {  // 同步注册回调函数到 异步的 宏任务队列。
            console.log(i);        // 执行此代码时，同步代码for循环已经执行完成
        }, 0);
    }
    // i虽然在全局作用域声明，但是在for循环体局部作用域中使用的时候，变量会被固定，不受外界干扰。
    for (let i = 0; i < 10; i++) {
        setTimeout(function() {
            console.log(i);    //  i 是循环体内局部作用域，不受外界影响。
        }, 0);
    }
    // 输出结果：0 1 2 3 4 5 6 7 8 9

    var foo = [];
    for (var i = 0; i < 10; i++) {
        foo[i] = function () {
            console.log(i);
        };
    }
    foo[6](); // 10
    console.log("---")
    /*
     * 上面代码中，变量 i 是 var 命令声明的，在全局范围内都有效，
     * 所以 全局只有一个变量 i 。每一次循环，变量 i 的值都会发生改变，
     * 而循环内被赋给数组 a 的函数内部的 console.log(i) ,里面的 i 指向的 就是全局的 i 。
     * 也就是说，所有数组 a 的成员里面的i ，指向的都 是同一个 i ，导致运行时输出的是最后一轮的 i 的值，
     * 也就是10。 如果使用 let，声明的变量仅在块级作用域内有效，最后输出的是6。
     */

    /**
     * for循环的条件体是一个父作用域
     * 他的循环体是个单独的子作用域
     * 由下面这个可以看出循环变量i和循环体内部变量i不是同一个作用域
     */
    for (let i = 0; i < 3; i++) {
        let i = 'abc';
        console.log(i);
    }
    // abc
    // abc
    // abc

    /**
     * 暂时性死区(Temporary Dead Zone, TDZ)
     *
     * 在代码块内，使用let命令声明变量之前，这个变量都是不可用的，这一块区域称为暂时性死区
     * ES6明确规定，如果区块中存在 let 和 const 命令，
     * 这个区块对这些命令声明的变量，从一开始就形成了封闭作用域。
     * 凡是在声明之前就使用这些变量，就会报错。
     */
        // var tmp = 123;
        // if (tmp){
        //     tmp = 'abc';
        //     let tmp;
        // }

    let x
    console.log(typeof x);

    /**
     * 立即执行函数存在的意义 主要就是为了隔离作用域
     */
    (function () {
        var temp = "立即执行函数作用域temp";
    })()

    console.log(temp)
    //  Uncaught ReferenceError: temp is not defined
    {
        let temp = "块级作用域temp";
    }
    console.log(temp)
    //  Uncaught ReferenceError: temp is not defined

</script>
